package com.apes.fn.scm.retailOrder.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.business.fixedLoss.modle.LossQuotation;
import com.apes.fn.business.fixedLoss.repository.LossQuotationRepository;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountData;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountService;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.servicePlan.service.ServicePlanceService;
import com.apes.fn.server.workOrder.model.MaintenanceOrder;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 工单带安凭证
 *
 * @author wuq
 * @create 2020-05-21 10:05
 */
@Service
public class MaintenanceVoucherService extends DomainService {

    @Autowired
    private ServicePlanceService servicePlanceService;
    @Autowired
    private OrderPaintProductService orderPaintProductService;
    @Autowired
    private RetailAccountService retailAccountService;

    /**
     * 外协工单完工时生成采购凭证
     *
     * @param wrapper OutboxPayloadWrapper
     */
    @OutboxSubscriber(id = "local.MaintenanceVoucherService.createVoucher", name = "外协完工生成采购凭证")
    public void createVoucher(OutboxPayloadWrapper wrapper) {
        JSONArray array = ((JSONObject) JSONObject.parse(wrapper.getPayload())).getJSONArray("maintenanceOrders");
        if (array.size() == 0) return;
        List<MaintenanceOrder> maintenanceOrders =  array.stream().map(tempJson -> MapUtil.getO(tempJson, MaintenanceOrder.class)).collect(Collectors.toList());
        retailAccountService.process("outHelp", new RetailAccountData(maintenanceOrders));      // 生成外协采购凭证
    }

    /**
     * 创建内协凭证 门店方案
     *
     * @param request {"id": xx, "serviceDeptId": xx, "items": ["id": "xx"]}
     */
    public void createInnerHelpProcess(SimpleRequest request) {
        JSONObject json = request.getJO();
        if (StringUtils.isEmpty(json.getString("id"))) {throw new RuntimeException("生内协凭证时，未传入id 字段");}
        if (StringUtils.isEmpty(json.getString("serviceDeptId"))) {throw new RuntimeException("生内协凭证时，未传入serviceDeptId 字段");}

        ServicePlan servicePlan = SpringManager.getBean(ServicePlanRepository.class).findOne(json.getString("id"));
        // 增加委托定损 与 自定损内协 判断
        if ("LossQuotation".equals(servicePlan.getSourceBusinessType())) {
            LossQuotation lossQuotation = SpringManager.getBean(LossQuotationRepository.class).findOne(servicePlan.getSourceFrom());
            //  定损来源并且不是 委托定损 或者不是 工单内协 的就返回
            if ( !"委托定损".equals(lossQuotation.getOrderType().getName()) && !"lossSomeAssist".equals(servicePlan.getPlanType()) ) return;
        }

        // 获取基地门店信息(防止工单内协部门取数有误)
        Dept serviceDept = SpringManager.getBean(DeptRepository.class).findOne(json.getString("serviceDeptId"));
        if ( servicePlan.getBelongDept().getCompany().getId().equals( serviceDept.getCompany().getId() ) ) {
            // 同公司不生成内协凭证，但基地需要生成油漆凭证
            createPaintVoucher(serviceDept, json.getJSONArray("items"));
            return;
        }

        // 创建内协凭证
        RetailAccountData data = new RetailAccountData(servicePlan, getServicePlanItem(json.getJSONArray("items")), serviceDept);
        retailAccountService.process("innerHelp", data);
    }

    private List<ServicePlanItem> getServicePlanItem(JSONArray array){
        return array.stream().map( v -> {
            JSONObject temp = (JSONObject) v;
            ServicePlanItem servicePlanItem = SpringManager.getBean(ServicePlanItemRepository.class).findOne(temp.getString("id"));
            if (Objects.isNull(servicePlanItem)) throw new RuntimeException("根据传入的编码没有找到对应的明细记录，服务方案明细编码：" + temp.getString("id"));
            return servicePlanItem;
        }).collect(Collectors.toList());
    }

    /**
     * 检查基地是否需要生成凭证
     *
     * @param serviceDept 基地门店
     * @param array       门店服务方案内协明细
     * @return Voucher
     */
    private void createPaintVoucher(Dept serviceDept, JSONArray array) {
        List<ServicePlanItem> planItems = getServicePlanItem(array);
        // 根据门店方案获取基地方案
        List<ServicePlanItem> basePlanItems = getBaseServicePlanItems(planItems);

        // 判断是否生成油漆凭证
        basePlanItems.stream()
                .map(item -> orderPaintProductService.setPaintInfo(serviceDept.getId(), item))  // 找油漆采购的价格
                .collect(Collectors.groupingBy(ServicePlanItem::isPaintFlag))
                .forEach((flag, items) -> {
                    if (flag) {
                        RetailAccountData retailAccountData = new RetailAccountData();
                        retailAccountData.setServicePlanItems(items);
                        retailAccountService.process("serverPaint", retailAccountData);
                    }
                });
    }

    /**
     * 通过门店方案找到基地方案明细
     * @param servicePlanItemList 门店方案明细
     * @return List<ServicePlanItem>
     */
    private List<ServicePlanItem> getBaseServicePlanItems(List<ServicePlanItem> servicePlanItemList) {
        // 找到基地的服务方案明细
        List<ServicePlanItem> servicePlanItems = new ArrayList<>();
        servicePlanItemList.stream()
                .filter(servicePlanItem -> "inner".equals(servicePlanItem.getAssistType().getCode())
                        && servicePlanItem.getTerminationDate() == null && servicePlanItem.isServiceState())
                .forEach(
                        planItem -> {
                            ServicePlanItem basePlanItem = servicePlanceService.findCBPForServicePlan(planItem);
                            if (basePlanItem == null)
                                throw new RuntimeException("创建整单内协方案基地分销单时，根据门店方案未找到对应内协门店方案，门店方案号为：" + planItem.getId());
                            servicePlanItems.add(basePlanItem);
                        });
        if (servicePlanItems.size() == 0) throw new RuntimeException("创建整单内协方案基地分销单，在新框架中没有到找到对应的基地方案。");
        return servicePlanItems;
    }

}
